package it.localhost.deepthought.one.activity;

import it.localhost.deepthought.one.R;
import it.localhost.deepthought.one.common.PlayListener;
import it.localhost.deepthought.one.fragment.MessageDialogFragment;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.Locale;

import android.annotation.TargetApi;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.IntentSender.SendIntentException;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Build;
import android.os.Bundle;
import android.speech.tts.TextToSpeech;

import com.google.android.gms.analytics.GoogleAnalytics;
import com.google.android.gms.analytics.HitBuilders;
import com.google.android.gms.analytics.Tracker;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GooglePlayServicesUtil;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.common.api.ResultCallback;
import com.google.android.gms.drive.Drive;
import com.google.android.gms.games.Games;
import com.google.android.gms.games.GamesStatusCodes;
import com.google.android.gms.games.snapshot.Snapshot;
import com.google.android.gms.games.snapshot.SnapshotMetadataChange;
import com.google.android.gms.games.snapshot.Snapshots;

abstract class AbstractActivity extends Activity implements PlayListener, GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, ResultCallback<Snapshots.OpenSnapshotResult> {
	private static final String DEF_SAVE = "DEF_SAVE";
	public final static int STATE_KEY = 0;
	protected GoogleApiClient googleApiClient;
	private Tracker tracker;
	protected int maxLevel;
	private TextToSpeech tts;
	protected Snapshot snapshot;

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		tracker = GoogleAnalytics.getInstance(this).newTracker(R.xml.analytics);
		googleApiClient = new GoogleApiClient.Builder(this, this, this).addApi(Games.API).addApi(Drive.API).addScope(Games.SCOPE_GAMES).addScope(Drive.SCOPE_APPFOLDER).build();
		NetworkInfo ni = ((ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE)).getActiveNetworkInfo();
		if (ni != null && ni.isConnectedOrConnecting()) {
			if (GooglePlayServicesUtil.isGooglePlayServicesAvailable(this) == ConnectionResult.SUCCESS)
				tts = new TextToSpeech(this, new TextToSpeechOnInitListener());
			else
				new MessageDialogFragment().show(this, R.string.error, R.string.errorPlayServices, true);
		} else
			new MessageDialogFragment().show(this, R.string.error, R.string.errorNetwork, true);
	}

	@Override
	public void onActivityResult(int requestCode, int resultCode, Intent data) {
		super.onActivityResult(requestCode, resultCode, data);
		if (requestCode == GoogleApiClient.class.hashCode()) {
			if (resultCode == RESULT_OK)
				googleApiClient.connect();
			else {
				new MessageDialogFragment().show(this, R.string.error, R.string.errorLogin, true);
				googleApiClient.disconnect();
			}
		}
	}

	@Override
	public void onDestroy() {
		super.onDestroy();
		if (googleApiClient.isConnected())
			googleApiClient.disconnect();
		if (tts != null) {
			tts.stop();
			tts.shutdown();
		}
	}

	public void sendEvent(String category, String action, String label) {
		tracker.send(new HitBuilders.EventBuilder(category, action).setLabel(label).build());
	}

	@SuppressWarnings("deprecation")
	@TargetApi(Build.VERSION_CODES.LOLLIPOP)
	public void speak(int res) {
		if (tts.isLanguageAvailable(Locale.getDefault()) >= TextToSpeech.LANG_AVAILABLE)
			if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
				tts.speak(getString(res), TextToSpeech.QUEUE_FLUSH, null, null);
			else
				tts.speak(getString(res), TextToSpeech.QUEUE_FLUSH, null);
	}

	@Override
	public void onConnected(Bundle connectionHint) {
		openSnapshot();
	}

	protected void openSnapshot() {
		Games.Snapshots.open(googleApiClient, DEF_SAVE, true).setResultCallback(this);
	}

	@Override
	public void onConnectionSuspended(int cause) {
		onSignOut();
	}

	@Override
	public void onConnectionFailed(ConnectionResult result) {
		if (result.hasResolution())
			try {
				result.startResolutionForResult(AbstractActivity.this, GoogleApiClient.class.hashCode());
			} catch (SendIntentException e) {
				googleApiClient.connect();
			}
		else
			new MessageDialogFragment().show(AbstractActivity.this, R.string.error, R.string.errorLogin, true);
	}

	@Override
	public void onResult(Snapshots.OpenSnapshotResult result) {
		int status = result.getStatus().getStatusCode();
		if (status == GamesStatusCodes.STATUS_OK || status == GamesStatusCodes.STATUS_SNAPSHOT_CONTENTS_UNAVAILABLE) {
			snapshot = result.getSnapshot();
			byte[] localData = null;
			try {
				localData = snapshot.getSnapshotContents().readFully();
			} catch (IOException e) {
				e.printStackTrace();
			}
			if (localData != null && localData.length > 0) {
				maxLevel = ByteBuffer.wrap(localData).getInt();
				onSignIn();
			} else {
				snapshot.getSnapshotContents().writeBytes(ByteBuffer.allocate(4).putInt(0).array());
				Games.Snapshots.commitAndClose(googleApiClient, snapshot, SnapshotMetadataChange.EMPTY_CHANGE);
				maxLevel = 0;
				onSignIn();
			}
		} else if (status == GamesStatusCodes.STATUS_SNAPSHOT_CONFLICT) {
			long snapTS = result.getSnapshot().getMetadata().getLastModifiedTimestamp();
			long cSnapTS = result.getConflictingSnapshot().getMetadata().getLastModifiedTimestamp();
			Games.Snapshots.resolveConflict(googleApiClient, result.getConflictId(), snapTS < cSnapTS ? result.getConflictingSnapshot() : result.getSnapshot()).setResultCallback(this);
		}
	}

	private final class TextToSpeechOnInitListener implements TextToSpeech.OnInitListener {
		@Override
		public void onInit(int status) {
			googleApiClient.connect();
			if (status != TextToSpeech.SUCCESS) {
				tts.stop();
				tts.shutdown();
			}
		}
	}
}